home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / misc / unix / tracker_4_3.lzh / tracker / lookup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-13  |  6.0 KB  |  269 lines

  1. /* lookup.c 
  2.     vi:se ts=3 sw=3:
  3.  */
  4.  
  5. /* A simple database lookup.
  6.  * every entry in the database files is of the form: initial string value
  7.  * We just have to match the initial string, no separators required.
  8.  * Not that the specification just asks for a matching entry, not
  9.  * necessarily the first or the last.
  10.  */
  11. /* $Id: lookup.c,v 4.0 1994/01/11 17:49:04 espie Exp espie $ */
  12.  
  13. /* $Log: lookup.c,v $
  14.  * Revision 4.0  1994/01/11  17:49:04  espie
  15.  * *** empty log message ***
  16.  *
  17.  * Revision 1.3  1994/01/09  17:36:22  Espie
  18.  * Generalized open.c.
  19.  *
  20.  * Revision 1.2  1994/01/05  14:54:09  Espie
  21.  * *** empty log message ***
  22.  *
  23.  * Revision 1.1  1993/12/26  00:55:53  Espie
  24.  * Initial revision
  25.  *
  26.  * Revision 1.2  1992/07/22  14:50:25  espie
  27.  * open_file changed, so lookup had to change to incorporate paths as well.
  28.  *
  29.  * Revision 1.1  1992/07/16  17:02:00  espie
  30.  * Initial revision
  31.  *
  32.  *
  33.  */
  34.  
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <malloc.h>
  38.  
  39. #include "defs.h"
  40. #include "extern.h"
  41.  
  42. ID("$Id: lookup.c,v 4.0 1994/01/11 17:49:04 espie Exp espie $")
  43.  
  44. /* the lookup structure is PRIVATE */
  45.  
  46. #define HANDLE 0    /* a null type, for memory handling */
  47. #define FNAME 1     /* a filename, which has not yet been opened */
  48. #define FOPENED 2   /* a file, once opened */
  49. #define STRING 3    /* an already accounted for string */
  50.  
  51. struct lookup
  52.    {
  53.    int type;
  54.    union 
  55.       {
  56.       char *filename;
  57.       FILE *file;
  58.       char *string;
  59.       char *path;
  60.       } value;
  61.    struct lookup *next;
  62.    };
  63.  
  64. /***
  65.  *
  66.  * lookup memory handling 
  67.  *
  68.  ***/
  69.  
  70. /* link_lookup(base, new): link a new element inside the existing chain */
  71. LOCAL void link_lookup(handle, new)
  72. struct lookup *handle, *new;
  73.    {
  74.    new->next = handle->next;
  75.    handle->next = new;
  76.    }
  77.  
  78. LOCAL void set_lookup(handle, path)
  79. struct lookup *handle;
  80. char *path;
  81.    {
  82.    handle->type = HANDLE;
  83.    handle->value.path = path;
  84.    }
  85.  
  86. /* new = create_lookup(): create an empty element, 
  87.  * chain anchor or to be filled 
  88.  */
  89. struct lookup *create_lookup(path)
  90. char *path;
  91.    {
  92.    struct lookup *new;
  93.  
  94.    new = (struct lookup *)malloc(sizeof(struct lookup));
  95.    if (!new)
  96.       exit(10);
  97.    set_lookup(path);
  98.    new->next = NULL;
  99.    return new;
  100.    }
  101.  
  102. /* free_lookup(handle): free the whole chain. Note that filenames
  103.  * do not belong to us
  104.  */
  105. void free_lookup(handle)
  106. struct lookup *handle;
  107.    {
  108.    struct lookup *to_free;
  109.  
  110.    while(handle)
  111.       {
  112.       to_free = handle;
  113.       handle = handle->next;
  114.       switch(to_free->type)
  115.          {
  116.       case HANDLE:
  117.       case FNAME: /* filenames don't belong to you */
  118.          break;
  119.       case FOPENED:
  120.          close_file(to_free->value.file.fhandle, 
  121.             to_free->value.file.filetype);
  122.          break;
  123.       case STRING:
  124.          free(to_free->value.string);
  125.          break;
  126.          }
  127.       free(to_free);
  128.       }
  129.    }
  130.  
  131. /* add_lookup(handle, filename): add a new potential filename to the lookup
  132.  * handle
  133.  */
  134. void add_lookup(handle, filename)
  135. struct lookup *handle;
  136. char *filename;
  137.    {
  138.    struct lookup *new;
  139.  
  140.    new = create_lookup();
  141.    new->type = FNAME;
  142.    new->value.filename = filename;
  143.    link_lookup(handle, new);
  144.    }
  145.  
  146.  
  147. /* postfix = check_prefix(template, s):
  148.  * if s is a prefix of template, return the remaining part of template,
  149.  * else return NULL.
  150.  * Note difference between NULL result and empty postfix (pointer to NULL)
  151.  */
  152. static char *check_prefix(template, s)
  153. char *template;
  154. char *s;
  155.    {
  156.    for (; *s; template++, s++)
  157.       /* *s != 0 at that point */
  158.       if (*template != *s)
  159.          return NULL;
  160.    while(*template == ' ' || *template == '\t')
  161.       template++;
  162.    return template;
  163.    }
  164.  
  165. /* copy = create_copy(s): allocate memory and create a copy of string s.
  166.  * get rid of spurious \n at the end.
  167.  */
  168. static char *create_copy(s)
  169. char *s;
  170.    {
  171.    char *new;
  172.    int len;
  173.  
  174.    len = strlen(s);
  175.    while(s[len - 1] == '\n')
  176.       s[--len] = 0;
  177.    new = malloc(len + 1);
  178.    if (!new)
  179.       exit(10);
  180.    return strcpy(new, s);
  181.    }
  182.  
  183. #define BUFSIZE 1500
  184.  
  185. LOCAL char *internal_lookup();
  186.  
  187. /* postfix = lookup(handle, s): lookup string s in the database indexed by
  188.  * handle.
  189.  */
  190. char *lookup(handle, s)
  191. struct lookup *handle;
  192. char *s;
  193.    {
  194.       /* the internal handler also maintains a current path */
  195.    return internal_lookup(handle, s, NULL);
  196.    }
  197.  
  198.  
  199. LOCAL char *internal_lookup(handle, s, path)
  200. struct lookup *handle;
  201. char *s;
  202. char *path;
  203.    {
  204.    char *r;
  205.    static char buffer[BUFSIZE];
  206.    struct lookup *new;
  207.  
  208.    if (handle)
  209.       {
  210.       switch(handle->type)
  211.          {
  212.       case STRING:
  213.          r = check_string(handle->value.string, s);
  214.          if (r)
  215.             return r;
  216.          else
  217.             return internal_lookup(handle->next, s, path);
  218.       case HANDLE:
  219.          return internal_lookup(handle->next, s,
  220.             handle->value.path ? handle->value.path : path);
  221.       case FNAME:
  222.          r = internal_lookup(handle->next, s, path);
  223.          if (r)
  224.             return r;
  225.          else
  226.             {
  227.             if (handle->value.file = 
  228.                open_file(handle->value.filename, "r", path))
  229.                {
  230.                handle->type = FOPENED;
  231.                return internal_lookup(handle, s, path);
  232.                }
  233.             else
  234.                {
  235.                set_lookup(handle, NULL);
  236.                return NULL;
  237.                }
  238.             }
  239.       case FOPENED:
  240.          r = internal_lookup(handle->next, s, path);
  241.          if (r)
  242.             return r;
  243.          else
  244.             {
  245.             if (fgets(buffer, BUFSIZE, handle->value.file))
  246.                {
  247.                new = create_lookup(NULL);
  248.                new->type = STRING;
  249.                new->value.string = create_copy(buffer);
  250.                link_lookup(handle, new);
  251.                r = check_prefix(new->value.string, s);
  252.                if (r)
  253.                   return r;
  254.                else
  255.                   return internal_lookup(handle, s, path);
  256.                }
  257.             else
  258.                {
  259.                close_file(handle->value.file);
  260.                set_lookup(new, NULL);
  261.                }
  262.             }
  263.          }
  264.       }
  265.    else
  266.       return NULL;
  267.    }
  268.             
  269.